﻿using System;
using System.Collections.Generic;
using PacMan3D.Utils;
using Tao.OpenGl;
using System.IO;
using Tao.DevIl;
using PacMan3D.Exceptions;

namespace PacMan3D.Objects
{
    /// <summary>
    /// This class represents a Wall.
    /// </summary>
    public class WallBox : IRenderable, ICollidable
    {
        public Point3D Position { get; private set; }
        private float Lenght;
        
        private int DisplayListId = 0;
        private int TextureId = 0;

        private RGBAColor Color;

        public WallBox(Point3D position, float lenght)
        {
            this.Position = position;
            this.Lenght = lenght;

            this.TextureId = ResourceLoader.LoadResource(Constants.RES_TEXT_WALL);

            CreateDisplayList();

            this.Color = new RGBAColor(StandardColors.White, 1.0f);
        }


        public override void DrawObject()
        {
            Gl.glColor4f(this.Color.Red, this.Color.Green, this.Color.Blue, 1.0f);
            Gl.glEnable(Gl.GL_LIGHTING);
            Gl.glEnable(Gl.GL_TEXTURE_2D);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, this.TextureId);
            Gl.glTexEnvf(Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_MODE, Gl.GL_MODULATE);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glPushMatrix();
                // coloca a parede para a posição dela
                Gl.glTranslatef(this.Position.X, this.Position.Y + this.Lenght/2.0f, this.Position.Z);
                // chama a primitiva de desenho
                Gl.glCallList(this.DisplayListId);
            Gl.glPopMatrix();
            Gl.glDisable(Gl.GL_TEXTURE_2D);
            Gl.glDisable(Gl.GL_LIGHTING);
        }

        private void CreateDisplayList()
        {
            float halfLenght = this.Lenght / 2;

            this.DisplayListId = Gl.glGenLists(1);
            Gl.glNewList(this.DisplayListId, Gl.GL_COMPILE);
            Gl.glBegin(Gl.GL_QUADS);

            // Top Face
            Gl.glNormal3f(0.0f, 1.0f, 0.0f);
            Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-halfLenght, halfLenght, -halfLenght);
            Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(-halfLenght, halfLenght, halfLenght);
            Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(halfLenght, halfLenght, halfLenght);
            Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(halfLenght, halfLenght, -halfLenght);

            // Bottom Face
            Gl.glNormal3f(0.0f, -1.0f, 0.0f);
            Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-halfLenght, -halfLenght, -halfLenght);
            Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(halfLenght, -halfLenght, -halfLenght);
            Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(halfLenght, -halfLenght, halfLenght);
            Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(-halfLenght, -halfLenght, halfLenght);

            // Left Face
            Gl.glNormal3f(-1.0f, 0.0f, 0.0f);
            Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(-halfLenght, -halfLenght, -halfLenght);
            Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(-halfLenght, -halfLenght, halfLenght);
            Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-halfLenght, halfLenght, halfLenght);
            Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-halfLenght, halfLenght, -halfLenght);

            // Right face
            Gl.glNormal3f(1.0f, 0.0f, 0.0f);
            Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(halfLenght, -halfLenght, -halfLenght);
            Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(halfLenght, halfLenght, -halfLenght);
            Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(halfLenght, halfLenght, halfLenght);
            Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(halfLenght, -halfLenght, halfLenght);

            // Front Face
            Gl.glNormal3f(0.0f, 0.0f, 1.0f);
            Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(-halfLenght, -halfLenght, halfLenght);
            Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(halfLenght, -halfLenght, halfLenght);
            Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(halfLenght, halfLenght, halfLenght);
            Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-halfLenght, halfLenght, halfLenght);

            // Back Face
            Gl.glNormal3f(0.0f, 0.0f, -1.0f);
            Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(-halfLenght, -halfLenght, -halfLenght);
            Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-halfLenght, halfLenght, -halfLenght);
            Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(halfLenght, halfLenght, -halfLenght);
            Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(halfLenght, -halfLenght, -halfLenght);

            Gl.glEnd();
            Gl.glEndList();
        }

        #region ICollidable Members
        public float Size
        {
            get { return this.Lenght / 2; }
        }
        #endregion
    }
}
